/**
* AutoSWF - Cody Cushing. March 26, 2009
* Copyright (c) 2009 Cody Cushing
* No use restrictions. Maintain this notice in all versions. 
**/

package com.autoswf.core
{
	import flash.events.Event;
	import flash.utils.Dictionary;
	
	/**
	 * Adaptor for Link that allows proxying handler functions for tracking and automation. 
	 * Requires a unique id mapped to proxied function so it can be identified and invoked remotely.
	 */	
	public class HandlerObserver implements ILink
	{
		protected var _link:ILink;
		protected var _ids:Dictionary;
		
		
		/**
		 * This class requires a link to the automation tree, pass the client's node here. 
		 * 
		 * @param link  The entry point in the chain for bubbling and receiving automation events. 
		 */
		public function HandlerObserver(link:ILink)
		{
			_link = link;
			_ids = new Dictionary();
		}
		
		public function get id():String
		{
			return _link.id;
		}
		
		public function addChildLink(link:ILink):void
		{
			_link.addChildLink(link);
		}
		
		public function removeChildLink(link:ILink):void
		{
			_link.removeChildLink(link);
		}
		
		public function addParentLink(link:ILink):void
		{
			_link.addParentLink(link);
		}
		
		public function removeParentLink(link:ILink):void
		{
			_link.removeParentLink(link);
		}
		
		public function sendUp(object:*):void
		{
			_link.sendUp(object);
		}
		
		/**
		 * Check if the proposition is a handler id, invoke and pass event if so, pass down chain if not. 
		 */
		public function sendDown(object:*):Object
		{
			var transport:Transport = Transport(object);
			
			if(_ids.hasOwnProperty(transport.proposition))
			{
				return _ids[transport.proposition](transport.message);
			}
			return _link.sendDown(object);
		}
		
		
		/**
		 * Use this function in a controller when attaching listeners to components in a view. 
		 * 
		 * @param id       The handler id for tracking/automation.
		 * @param handler  The event handler for this event
		 * @return         A function that splices automation support between the event and the handler
		 */
		public function proxy(id:String, handler:Function):Function
		{
			if(_ids[id] == null)  /* If this method has not already been proxied */
			{
				_ids[id] = function(event:Event):void /* Splice a command in front of the handler */
				{
					_link.sendUp(new Transport(event).setPath(id)); /* Bubble events up */
					handler(event);                        /* Invoke handler */
				}
			}
			return _ids[id];
		}
		
		
		/**
		 * Delete the reference to the proxy function and return the reference so it can be removed 
		 * from any dispatcher.
		 * 
		 * @param handler  The event handler for this event
		 * @return         A function that splices automation support between the event and the handler
		 */
		public function deleteProxy(id:String):Function
		{
			if(!_ids.hasOwnProperty(id))
			{
				return null;
			}
			var func:Function = _ids[id];
			delete _ids[id];
			return func;
		}

	}
}